<?php

namespace app\admin\model;
use app\common\model\BaseModel;
use think\facade\Cache;

/**
 * 后台菜单模型
 * Class AdminMenu
 * @package app\admin\model
 */
class AdminMenu extends BaseModel
{
    protected $name = 'admin_menu';

    protected $pk = 'admin_menu_id';
    
    /**
     * 追加字段
     * @var array
     */
    protected $append = [
       
    ];

    
    /**
     * 隐藏字段
     * @var array
     */
    protected $hidden = [
        // 'update_time',
        // 'create_time'
    ];

    // 新增菜单
    public function add($param){
        if(empty($param['name']))
        {
            $this->error = "必须填写菜单名称";
            return false;
        }
        if(empty($param['url']))
        {
            $this->error = "必须填写菜单链接";
            return false;
        }
        try {
            $this->startTrans();
            // 新增
            $this->exists(false)->save($param);
            // 清除菜单缓存
            Cache::delete('menus');
            $this->commit();
            return true;
        } catch (\Throwable $th) {
            //throw $th;
            $this->error = $th->getMessage();
            $this->rollback();
            return false;
        }
    }

    // 编辑菜单
    public function edit($param){
        if(empty($param['admin_menu_id']))
        {
            $this->error = "菜单ID不能为空";
            return false;
        }
        if(empty($param['name']))
        {
            $this->error = "必须填写菜单名称";
            return false;
        }
        if(empty($param['url']))
        {
            $this->error = "必须填写菜单链接";
            return false;
        }
        try {
            $this->startTrans();
            // 更新
            $this->exists(true)->save($param);
            // 清除菜单缓存
            Cache::delete('menus');
            // 清理涉及改菜单的角色菜单缓存
            $roleList = (new AdminRole)->where('admin_role_id','<>',1)->whereFindInSet('admin_menu_id',$param['admin_menu_id'])->column('admin_role_id');
            $roleList[] = 1;
            $this->clearMenuCache($roleList);
            $this->commit();
            return true;
        } catch (\Throwable $th) {
            //throw $th;
            $this->error = $th->getMessage();
            $this->rollback();
            return false;
        }
    }

    /**
     *  根据权限角色ID清理对应缓存
     *  @return bool 
    */
    private function clearMenuCache($roleList){
        if(is_array($roleList))
        {
            foreach ($roleList as  $value) {
                // 清除菜单缓存
                Cache::delete('menus_'.$value);
            }
        }else
        {
            // 清除菜单缓存
            Cache::delete('menus_'.$roleList);
        }
        return true;
    }

    /**
     *  获取所有菜单
     *  @return array all 平铺 tree 树型
    */
    public function getMenuAll(){
        // 判断对应角色缓存是否存在
        if(!Cache::get('menus'))
        {
            // 查询对应菜单数组
            $menu_all  = $this->withoutField("update_time,create_time",true)->order('sort asc')->select();
            $result['all'] = $menu_all->toArray();
            $admin_authority_menu_url = [];
            // 无限极生成树型菜单
            $result['tree'] = $this->getTree($menu_all,0,$admin_authority_menu_url,1);
            // 存入缓存
            Cache::tag('cache')->set('menus',$result);
            Cache::tag('cache')->set('admin_authority_menu_url',$admin_authority_menu_url);
        }
        // 返回对应数据
        return Cache::get('menus');
    }

    /**
     * 获取角色菜单权限
     * @param int admin_authority_menu_id 用户权限菜单ID
     * @return array
    */ 
    public function getRoleAuthorityMenu($admin_role_info){
        // 判断对应角色缓存是否存在
        if(!Cache::get('menus_' . $admin_role_info['admin_role_id']))
        {
            $admin_authority_menu_url = [];
            // 无限极生成对应角色权限树型菜单 (前端不想做,去掉了)
            // if($admin_role_info['admin_role_id'] == 1)
            // {
            //     // 超级管理员获取全部菜单
            //     $result['menu'] = $this->getTree($this->getMenuAll()['all'],0,$admin_authority_menu_url,0);
            // }else
            // {
            // 非超级管理员 重新从缓存检索对应的权限菜单
            $result['menu'] = $this->getAuthorityMenuTree($admin_role_info['admin_menu_id'],$admin_authority_menu_url);
            // }
            
            // 存入缓存
            Cache::tag('cache')->set('menus_' . $admin_role_info['admin_role_id'],$result);
            Cache::tag('cache')->set('admin_authority_menu_url_' . $admin_role_info['admin_role_id'],$admin_authority_menu_url);
        }
        // 返回对应数据
        return Cache::get('menus_' .  $admin_role_info['admin_role_id']);
    }

    /**
     * 根据用户menu_ids获取权限菜单
     * @param array $menu_ids role表中对应的菜单id
     * @param string $admin_authority_menu_url 菜单权限路由
    */ 
    private function getAuthorityMenuTree($menu_ids,&$admin_authority_menu_url){
        // 将IDS转换成数组
        // $menu_ids = explode(',',$menu_ids);
        // 获取缓存中的所有菜单
        $menu_all = $this->getMenuAll()['all'];
        $menu_arr = [];
        // 根据菜单$menu_ids 获取权限菜单
        foreach ($menu_all as $value) {
            # code...
            if(in_array($value['admin_menu_id'],$menu_ids))
            {
                $menu_arr[] = $value;
            }
        }
        return $this->getTree($menu_arr,0,$admin_authority_menu_url);
    }

    /**
     * 无限极生成树型菜单
     * @param  array $data 要循环的菜单列表
     * @param  int $v['ishidden']  是否显示
     * @param  int $v['parent_id']  父ID
     * @param  int $v['admin_menu_id']  权限菜单ID
     * @param  string $v['url']  权限菜单请求地址
     * @param  int $pid 父ID
     * @param  array  $admin_authority_menu_url 权限菜单的url数组(内存指向)
     * @param  int 是否显示隐藏菜单
     */
    private function getTree($data, $pid,&$admin_authority_menu_url,$hide = 0)
    {
        $tree = [];
        foreach($data as $k => $v)
        {
            // if(!in_array(strtolower($v['url']),$admin_authority_menu_url))
            // {
                // 1.2版本,优化此处权限控制
                $admin_authority_menu_url[strtolower($v['url'])] = $v['admin_menu_id'];
            // }
            // 判断是否需要显示隐藏菜单
            if(($v['parent_id'] == $pid && $v['ishidden'] == 0) && $hide == 0)
            {   
                //父亲找到儿子(前端偷懒不想做菜单子菜单判断,之后我来了.)
                $child = $this->getTree($data, $v['admin_menu_id'],$admin_authority_menu_url,$hide);
                if($child)
                {
                    $v['child'] = $child;
                }
                $tree[] = $v;
            }elseif($v['parent_id'] == $pid && $hide == 1)
            {
                //父亲找到儿子(前端偷懒不想做菜单子菜单判断,之后我来了.)
                $child = $this->getTree($data, $v['admin_menu_id'],$admin_authority_menu_url,$hide);
                if($child)
                {
                    $v['child'] = $child;
                }
                $tree[] = $v;
            }
            
        }

        return $tree;
    }

    public function remove($admin_menu_id){
        try {
            $this->startTrans();
            // 查询下该菜单是否存在子菜单
            if($this->where(['parent_id'=>$admin_menu_id])->value('admin_menu_id'))
            {
                $this->error = "该菜单下面还有子菜单.无法删除!";
                $this->rollback();
                return false;
            }
            // 删除菜单
            if($this->where(['admin_menu_id'=>$admin_menu_id])->delete())
            {
                // 更新设置表
                Cache::delete('menus');
                $this->commit();
                return true;
            }
        } catch (\Throwable $th) {
            //throw $th;
            $this->error = $th->getMessage();
            $this->rollback();
            return false;
        }
    }
}